/**
 * Copyright 2011 Renato de Jesus Manzoni
 * 
 * SED - Software Engineering and Dependability Research Group
 * 
 *     http://www.sed.ic.unicamp.br/
 * 
 * Distributed Systems Laboratory (LSD) in the Institute of Computing (IC) at University of Campinas (UNICAMP)
 * 
 *     http://www.lsd.ic.unicamp.br/
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package br.unicamp.ic.lsd.wscaa.concurrent;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.endpoint.ClientCallback;

import br.unicamp.ic.lsd.wscaa.model.ServiceResponse;

/**
 * @author Renato de Jesus Manzoni <rjmanzoni@gmail.com>
 *
 */
public class WSCAACallBackResults {

	private List<ServiceResponseCallable> tasks;

	private static Log logger = LogFactory.getLog(WSCAACallBackResults.class);

	public WSCAACallBackResults() {

		tasks = new ArrayList<ServiceResponseCallable>();

	}

	public void addTask(String method, ClientCallback cb) {
		tasks.add(new ServiceResponseCallable(method, cb));
	}

	private List<ServiceResponse> synchronizeAllCallBacks() {
		List<ServiceResponse> responses = new ArrayList<ServiceResponse>();
		//qual deve ser o tamnho da threadpool?
		ExecutorService executor = Executors.newFixedThreadPool(10); 
		
		List<Future<ServiceResponse>> futures;

		try {
			futures = executor.invokeAll(tasks);
			// sync the results
			for (Iterator<Future<ServiceResponse>> iterator = futures
					.iterator(); iterator.hasNext();) {
				Future<ServiceResponse> fut = iterator.next();

				ServiceResponse res = fut.get();

				//just add if res is not null
				if (res != null) {
					
					if (logger.isTraceEnabled())
						logger.trace("The first result from "
								+ res.getResponseName() + " is "
								+ (res.hasException()? res.getException() : res.getReponses()[0]));

					responses.add(res);
				}

			}

			return responses;

		} catch (InterruptedException e) {

			logger.error(e.getLocalizedMessage(), e);

		} catch (ExecutionException e) {
			
			logger.error(e.getLocalizedMessage(), e);
		}
		return null;
	}

	public List<ServiceResponse> getResults() {
		return synchronizeAllCallBacks();
	}

	// public void synchronizeAllCallBacks2() {
	// Collection<String> keys = callBacksByOp.keySet();
	// final List<ServiceResponse> responses = new ArrayList<ServiceResponse>();
	//
	// for (Iterator<String> iterator = keys.iterator(); iterator.hasNext();) {
	//
	// final String key = iterator.next();
	//
	// final ClientCallback cb = callBacksByOp.get(key);
	//
	// Thread t = new Thread() {
	//
	// @Override
	// public void run() {
	// addResponse(key, cb, responses);
	// }
	// };
	// executor.execute(t);
	//
	// }
	//
	// //while(executor.getCompletedTaskCount() < MAX_INSERTIONS);
	//
	// }

	// supondo que tudo deu certo! rs
	// protected void addResponse(String method, ClientCallback cb,
	// List<ServiceResponse> responses) {
	//
	// try {
	//
	// Object[] results = cb.get();
	//
	// synchronized (responses) {
	// responses.add(new ServiceResponse(method, results));
	// }
	//
	// } catch (InterruptedException e) {
	// e.printStackTrace();
	// } catch (ExecutionException e) {
	// e.printStackTrace();
	// }
	//
	// }
}
